package com.funsport.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.funsport.entity.Event;
import com.funsport.entity.User;
import com.funsport.entity.Venue;
import com.funsport.exception.BusinessException;
import com.funsport.mapper.VenueMapper;
import com.funsport.service.IEventService;
import com.funsport.service.IUserService;
import com.funsport.service.IVenueService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

/**
 * Venue Service实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class VenueServiceImpl extends ServiceImpl<VenueMapper, Venue> implements IVenueService {

    private final IUserService userService;
    private final IEventService eventService;

    @Override
    @Transactional
    public boolean createVenue(Venue venue, Long managerId) {
        // 验证管理员权限
        User manager = userService.getById(managerId);
        if (manager == null) {
            throw new BusinessException("管理员不存在");
        }

        if (!"venue_manager".equals(manager.getRole()) && !"admin".equals(manager.getRole())) {
            throw new BusinessException("只有场地管理员或系统管理员可以创建场地");
        }

        venue.setManagerId(managerId);
        venue.setStatus("active");
        
        boolean result = save(venue);
        
        if (result) {
            log.info("场地创建成功: venueId={}, managerId={}", venue.getId(), managerId);
        }
        
        return result;
    }

    @Override
    public boolean isVenueAvailable(Long venueId, LocalDateTime startTime, LocalDateTime endTime) {
        Venue venue = getById(venueId);
        if (venue == null) {
            throw new BusinessException("场地不存在");
        }

        if (!"active".equals(venue.getStatus())) {
            return false;
        }

        // 查询该时间段是否有冲突的预订
        List<Event> conflictEvents = eventService.list(new LambdaQueryWrapper<Event>()
                .eq(Event::getVenueId, venueId)
                .and(wrapper -> wrapper
                        .between(Event::getStartTime, startTime, endTime)
                        .or()
                        .between(Event::getEndTime, startTime, endTime)
                        .or()
                        .and(w -> w
                                .le(Event::getStartTime, startTime)
                                .ge(Event::getEndTime, endTime)
                        )
                )
                .ne(Event::getStatus, "CANCELLED"));

        return conflictEvents.isEmpty();
    }

    @Override
    @Transactional
    public boolean bookVenue(Long venueId, Long eventId, LocalDateTime startTime, LocalDateTime endTime, Long userId) {
        // 检查场地是否存在
        Venue venue = getById(venueId);
        if (venue == null) {
            throw new BusinessException("场地不存在");
        }

        // 检查是否有权限预订
        if (!venue.getManagerId().equals(userId)) {
            // 检查是否是活动创建者
            Event event = eventService.getById(eventId);
            if (event == null || !event.getCreatorId().equals(userId)) {
                throw new BusinessException("您没有权限预订该场地");
            }
        }

        // 检查时间段是否可用
        if (!isVenueAvailable(venueId, startTime, endTime)) {
            throw new BusinessException("该时间段场地不可用");
        }

        // 更新活动的场地信息
        Event event = eventService.getById(eventId);
        if (event != null) {
            event.setVenueId(venueId);
            eventService.updateById(event);
        }

        log.info("场地预订成功: venueId={}, eventId={}, userId={}", venueId, eventId, userId);
        return true;
    }

    @Override
    @Transactional
    public boolean cancelVenueBooking(Long venueId, Long eventId) {
        Event event = eventService.getById(eventId);
        if (event == null) {
            throw new BusinessException("活动不存在");
        }

        if (!venueId.equals(event.getVenueId())) {
            throw new BusinessException("该活动未预订此场地");
        }

        // 清除活动的场地信息
        event.setVenueId(null);
        eventService.updateById(event);

        log.info("场地预订已取消: venueId={}, eventId={}", venueId, eventId);
        return true;
    }

    @Override
    public List<Venue> getVenueBookings(Long venueId, LocalDateTime startDate, LocalDateTime endDate) {
        // 这个方法的实现需要根据实际的预订记录表来调整
        // 目前我们通过关联的Event来获取预订信息
        // 实际项目中可能需要单独的VenueBooking表
        
        // 暂时返回空列表，实际应该查询预订记录
        log.info("查询场地预订记录: venueId={}, startDate={}, endDate={}", venueId, startDate, endDate);
        return Collections.emptyList();
    }

    @Override
    public List<Venue> searchVenues(String city, Long sportTypeId) {
        LambdaQueryWrapper<Venue> query = new LambdaQueryWrapper<Venue>()
                .eq(Venue::getStatus, "active");

        if (city != null && !city.isEmpty()) {
            query.eq(Venue::getCity, city);
        }

        // Venue的sportTypes是字符串格式，暂时不支持精确匹配
        // if (sportTypeId != null) {
        //     query.like(Venue::getSportTypes, sportTypeId.toString());
        // }

        return list(query);
    }

    @Override
    public List<Venue> getVenuesByManager(Long managerId) {
        return list(new LambdaQueryWrapper<Venue>()
                .eq(Venue::getManagerId, managerId)
                .orderByDesc(Venue::getCreatedAt));
    }

    @Override
    @Transactional
    public boolean updateVenueStatus(Long venueId, String status, Long managerId) {
        Venue venue = getById(venueId);
        if (venue == null) {
            throw new BusinessException("场地不存在");
        }

        // 验证权限
        if (!venue.getManagerId().equals(managerId)) {
            // 检查是否是系统管理员
            User manager = userService.getById(managerId);
            if (manager == null || !"admin".equals(manager.getRole())) {
                throw new BusinessException("您没有权限修改该场地状态");
            }
        }

        venue.setStatus(status);
        boolean result = updateById(venue);

        if (result) {
            log.info("场地状态已更新: venueId={}, status={}, operatorId={}", venueId, status, managerId);
        }

        return result;
    }
}
